Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support logging into a registry if necessary #787

Conversation

HarryMichal
Copy link
Member

@HarryMichal HarryMichal commented Jun 7, 2021

This introduces handling of registries with private repositories/images. Practically speaking, if a used image lives in a registry behind a login wall, Toolbox will be aware of the fact and asks the user if they want to log in. This can be automated by combining the existing global --assumeyes option with newly introduced options --authfile and --creds in command create.

The authentication is done by Podman and Toolbox only serves as a mediator between the user and Podman. It does not record/store user's credentials in any way.

Examples of the new behaviour:

# Try to create from an unknown image
$ toolbox create -i registry.fedoraproject.org/no-image
Image required to create toolbox container.
Download registry.fedoraproject.org/no-image (500MB)? [y/N]: y
Error: The requested image does not exist
Make sure the image URI is correct.

# Try to create from an image in registry with authentication
$ toolbox -y create -i registry.redhat.io/image
Image required to create toolbox container.
Download registry.redhat.io/image (500MB)? [y/N]: y
The registry requires logging in.
Do you want to log into the registry and try to pull the image again? [y/N]: y
Username: <username>
Password:
Retrying to pull image registry.redhat.io/image
Created container: image-toolbox
Enter with: toolbox enter image-toolbox

# Create from an image in registry with authentication by providing login credentials
$ toolbox -y create -i registry.redhat.io/image --creds <username>:<password>
Could not pull image registry.redhat.io/image
The registry requires logging in.
Credentials were provided. Trying to log into registry.redhat.io
Login Succeeded!
Retrying to pull image registry.redhat.io/image
Created container: image-toolbox
Enter with: toolbox enter image-toolbox

Depends on #786, #823

Closes #754

@HarryMichal HarryMichal added 3. Enhancement Improvement to an existing feature 6. Major Change May cause breakage 2. Host Realm The issue is related to what happens on the host machine where Toolbox is executed 2. Under The Hood Multiple areas of the app are influenced by this ticket labels Jun 7, 2021
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 7, 2021
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from 1155a56 to fc636da Compare June 7, 2021 19:55
@HarryMichal HarryMichal changed the title cmd/create, pkg/podman: Add capabilities for logging to registries cmd/create, pkg/podman: Add capabilities for loging to registries Jun 7, 2021
@softwarefactory-project-zuul
Copy link

Build succeeded.

HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 8, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in.

The parsing process is quite fragile since Podman does not provide clear
means to distinguish such cases and provided messages differ between
registries. This should distinguish authorization errors with
registry.redhat.io and docker.io.

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, not everything added/changed by this will be
tested. In the future we'll have to start mocking servers to be able to
do so.

containers#787
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from fc636da to 6808d35 Compare June 8, 2021 09:05
@softwarefactory-project-zuul
Copy link

Build failed.

HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 8, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in.

The parsing process is quite fragile since Podman does not provide clear
means to distinguish such cases and provided messages differ between
registries. This should distinguish authorization errors with
registry.redhat.io and docker.io.

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, not everything added/changed by this will be
tested. In the future we'll have to start mocking servers to be able to
do so.

containers#787
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from 6808d35 to bbcd5e1 Compare June 8, 2021 09:17
@softwarefactory-project-zuul
Copy link

Build failed.

@HarryMichal
Copy link
Member Author

recheck

@softwarefactory-project-zuul
Copy link

Build failed.

@HarryMichal HarryMichal marked this pull request as ready for review June 9, 2021 11:32
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 9, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in.

The parsing process is quite fragile since Podman does not provide clear
means to distinguish such cases and provided messages differ between
registries. This should distinguish authorization errors with
registry.redhat.io and docker.io.

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, not everything added/changed by this will be
tested. In the future we'll have to start mocking servers to be able to
do so.

containers#787
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from bbcd5e1 to 4ab6577 Compare June 9, 2021 20:09
@softwarefactory-project-zuul
Copy link

Build succeeded.

@HarryMichal HarryMichal requested a review from debarshiray June 9, 2021 20:58
@HarryMichal
Copy link
Member Author

HarryMichal commented Jun 9, 2021

I may have gotten an idea on how to test this reliably. Until I have it figured out or I give up, let's postpone merging this.

EDIT: I also found more info regarding the parsed error messages. I started to make more sense of them :). All thanks to reading the documentation \o/.

return nil
}

// Pull pulls an image. Wraps around command 'podman pull'.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra pulls

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is intentional since Go tooling requires function comments to start with the name of the function. But I'd reword the function anyway :).

HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 12, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in or tell the user that the requested image/manifest does not exist.

The parsing process relies on error messages that match the OCI
specification[0].

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, as part of the setup two local image registries
are created and these features can be tested against them. To prevent
the removal of the registries during testing a flag --namespace is used
in Podman during their creation.

[0] https://github.com/opencontainers/distribution-spec/blob/main/spec.md#error-codes

containers#787
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from 4ab6577 to b160671 Compare June 12, 2021 16:56
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 12, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in or tell the user that the requested image/manifest does not exist.

The parsing process relies on error messages that match the OCI
specification[0].

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, as part of the setup two local image registries
are created and these features can be tested against them. To prevent
the removal of the registries during testing a flag --namespace is used
in Podman during their creation.

[0] https://github.com/opencontainers/distribution-spec/blob/main/spec.md#error-codes

containers#787
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from b160671 to b88cc96 Compare June 12, 2021 17:01
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 12, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in or tell the user that the requested image/manifest does not exist.

The parsing process relies on error messages that match the OCI
specification[0].

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, as part of the setup two local image registries
are created and these features can be tested against them. To prevent
the removal of the registries during testing a flag --namespace is used
in Podman during their creation.

[0] https://github.com/opencontainers/distribution-spec/blob/main/spec.md#error-codes

containers#787
@HarryMichal HarryMichal force-pushed the cmd/create/support-registry-authentication branch from b88cc96 to 12b766c Compare June 12, 2021 17:07
HarryMichal added a commit to HarryMichal/toolbox that referenced this pull request Jun 12, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offer the user the means to log
in or tell the user that the requested image/manifest does not exist.

The parsing process relies on error messages that match the OCI
specification[0].

Testing of this feature is tricky as it relies on network which is
inherently flaky. So, as part of the setup two local image registries
are created and these features can be tested against them. To prevent
the removal of the registries during testing a flag --namespace is used
in Podman during their creation.

[0] https://github.com/opencontainers/distribution-spec/blob/main/spec.md#error-codes

containers#787
@softwarefactory-project-zuul
Copy link

Build failed.

debarshiray pushed a commit to HarryMichal/toolbox that referenced this pull request Jul 4, 2021
debarshiray pushed a commit to HarryMichal/toolbox that referenced this pull request Jul 4, 2021
debarshiray added a commit to HarryMichal/toolbox that referenced this pull request Jul 4, 2021
A subsequent commit will use this when retrying the 'podman pull'
after logging the user into the registry for images that require
authorization.

containers#787
debarshiray pushed a commit to HarryMichal/toolbox that referenced this pull request Jul 4, 2021
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offers the user the means to
log in.

Some changes by Debarshi Ray.

containers#787
debarshiray pushed a commit to HarryMichal/toolbox that referenced this pull request Jul 4, 2021
Testing of this feature is tricky as it relies on network which is
inherently flaky. So, as part of the setup two local image registries
are created and these features can be tested against them. To prevent
the removal of the registries during testing a different root for Podman
is used. The only tested registry implementation is Docker[0].

[0] https://hub.docker.com/_/registry/

containers#787
debarshiray pushed a commit to HarryMichal/toolbox that referenced this pull request Jul 4, 2021
The new additions to the system tests makes them take longer to run,
and was causing them to timeout.

containers#787
@debarshiray debarshiray force-pushed the cmd/create/support-registry-authentication branch from ce01f2a to f160b2e Compare July 4, 2021 22:30
Copy link
Member

@debarshiray debarshiray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of things about the test suite:

(You did a really good job setting up the registries as part of the test suite! Well done.)

load 'libs/helpers'

@test "test suite: Setup" {
# Cache the default image for the system
_pull_and_cache_distro_image $(get_system_id) $(get_system_version) || die
# Cache all images that will be needed during the tests
_pull_and_cache_distro_image fedora 32 || die
_pull_and_cache_distro_image rhel 8.4 || die
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use a Fedora (or anything that's not UBI) image for testing?

$PODMAN --root "$PODMAN_REG_ROOT" logs docker-registry-auth

# Add UBI8 to created registries
run $SKOPEO copy "dir:${IMAGE_CACHE_DIR}/fedora-toolbox-32" "docker://localhost:50000/fedora-toolbox:32"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the comment? Is the comment really necessary? We didn't use one for the similar statement below. :)

@softwarefactory-project-zuul
Copy link

Build failed.

@debarshiray debarshiray changed the title cmd/create, pkg/podman: Add capabilities for logging to registries Support logging into a registry if necessary Jul 4, 2021
HarryMichal and others added 9 commits July 5, 2021 01:12
This is meant to get a better understanding of a failed 'podman pull'
invocation to understand whether pulling an image requires logging into
the registry or not. Currently, 'podman pull' doesn't have a dedicated
exit code to denote authorization errors, so this is meant to be a
temporary workaround for that.

Parsing the error stream is inherently fragile and tricky because
there's no guarantee that the structure of the messages won't change,
and there's no clear definition of how the messages are laid out.
Therefore, this approach can't be treated as a generic solution for
getting detailed information about failed Podman invocations.

The error stream is used not only for dumping error messages, but also
for showing progress bars. Therefore, all lines are skipped until one
that starts with "Error: " is found. This is a heuristic based on how
Go programs written using the Cobra [1] library tend to report errors.

All subsequent lines are taken together and split around the ": "
sub-string, on the assumption that the ": " sub-string is used when a
new error message is prefixed to an inner error. Each sub-string
created from the split is treated as a potential member of the chain of
errors reported within Podman.

Some real world examples of the 'podman pull' error stream in the case
of authorization errors are:

  * With Docker Hub (https://hub.docker.com/):
    Trying to pull docker.io/library/foobar:latest...
    Error: Error initializing source docker://foobar:latest: Error reading manifest latest in docker.io/library/foobar: errors:
    denied: requested access to the resource is denied
    unauthorized: authentication required

  * With registry.redhat.io:
    Trying to pull registry.redhat.io/foobar:latest...
    Error: Error initializing source docker://registry.redhat.io/foobar:latest: unable to retrieve auth token: invalid username/password: unauthorized: Please login to the Red Hat Registry using your Customer Portal credentials. Further instructions can be found here: https://access.redhat.com/RegistryAuthentication

[1] https://github.com/spf13/cobra/
    https://pkg.go.dev/github.com/spf13/cobra

containers#689
containers#786
containers#787
This way the standard error stream of the spawned binaries can be
inspected to get a better understanding of the failure, while still
being shown to the user when run with the '--verbose' flag.

Unfortunately, this breaks the progress bar in 'podman pull' because
the standard error stream is no longer connected to a file descriptor
that's a terminal device.

containers#689
containers#787
containers#823
A subsequent commit will use this when retrying the 'podman pull'
after logging the user into the registry for images that require
authorization.

containers#689
containers#787
Some registries contain private repositories of images and require the
user to log in first to gain access. With this Toolbox tries to
recognize errors when pulling images and offers the user the means to
log in.

Some changes by Debarshi Ray.

containers#689
containers#787
Testing of this feature is tricky as it relies on network which is
inherently flaky. So, as part of the setup two local image registries
are created and these features can be tested against them. To prevent
the removal of the registries during testing a different root for Podman
is used. The only tested registry implementation is Docker[0].

[0] https://hub.docker.com/_/registry/

containers#689
containers#787
The new additions to the system tests makes them take longer to run,
and was causing them to timeout.

containers#689
containers#787
@debarshiray debarshiray force-pushed the cmd/create/support-registry-authentication branch from f160b2e to ba2fc50 Compare July 4, 2021 23:13
@softwarefactory-project-zuul
Copy link

Build failed.

@debarshiray
Copy link
Member

Unless podman pull grows a dedicated exit code to denote authorization errors, we can't merge this upstream. However, downstream distributors who want this feature can use this patch-set at their own risk.

In the absence of a dedicated exit code from podman pull, this patch-set tries to parse the standard error stream of podman pull to guess whether the image requires logging into the registry or not. This sort of screen scraping is very fragile and is a bad idea.

First, the messages that get dumped in the error stream don't have any fixed structure or format, and can change from one Podman version to another. Moreover, the error stream is also used to show things like progress bars, so those need to be skipped when parsing it. This makes it very fragile to test whether the parsing works as expected across several Podman versions in several operating systems.

Second, since the error stream is also used to show progress bars for podman pull, redirecting it away from a terminal device (to intercept its contents) prevents the progress bar from being shown. We show the progress bar when toolbox --verbose ... is used because they are useful for checking the status of the pulls. Ultimately, we are downloading hundreds of megabytes as part of a critical operation, so having access to a working progress bar is important.

So, long story short, we either need podman pull to have a dedicated exit code for authorization failures, or we need to re-implement podman pull directly inside Toolbox so that we have better access to the errors.

@HarryMichal
Copy link
Member Author

I'll close this since this approach is not acceptable long-term-wise. If the work is attempted again, it can be done in a separate PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2. Host Realm The issue is related to what happens on the host machine where Toolbox is executed 2. Under The Hood Multiple areas of the app are influenced by this ticket 3. Enhancement Improvement to an existing feature 6. Major Change May cause breakage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Registry authentication is not supported
3 participants